package com.edwin.websitebe.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.edwin.websitebe.model.*;
import com.edwin.websitebe.service.*;
import com.edwin.websitebe.util.OSSUtil;
import com.edwin.websitebe.util.TokenUtil;
import com.edwin.websitebe.vo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Edwin
 */

@RestController
@RequestMapping("/game")
@Slf4j
@CrossOrigin
public class GameController {

    @Autowired
    private TopGameService topGameService;

    @Autowired
    private GameService gameService;

    @Autowired
    private GameTypeMapService gameTypeMapService;

    @Autowired
    private GameTypeService gameTypeService;

    @Autowired
    private MemberGameService memberGameService;

    @GetMapping("/listRecommendGame")
    public ResultVO listRecommendGame() {
        LambdaQueryWrapper<Game> wrapper = new QueryWrapper<Game>().lambda()
                .eq(Game::getIsRecommend, Boolean.TRUE)
                .orderByAsc(Game::getGameCode);
        List<Game> recommendGameList = gameService.list(wrapper);
        return new ResultVO().success(recommendGameList);
    }

    @GetMapping("/getTopGame")
    public ResultVO getTopGame() {
        TopGame topGame = topGameService.get();
        return new ResultVO().success(topGame);
    }

    @GetMapping("/getById")
    public ResultVO getById(@RequestParam Long id) {
        Game game = gameService.getById(id);
        if (game != null) {
            List<GameTypeMap> gameTypeMaps = gameTypeMapService.listByGameId(id);
            List<Long> typeIdList = gameTypeMaps.stream()
                    .map(GameTypeMap::getTypeId)
                    .distinct()
                    .collect(Collectors.toList());
            game.setTypeIdList(typeIdList);
        }

        return new ResultVO().success(game);
    }

    @GetMapping("/get")
    public ResultVO get(@RequestParam Long id, HttpServletRequest request) {
        Game game = gameService.getById(id);
        if (game != null) {

            String token = request.getHeader(HttpHeaders.AUTHORIZATION);
            Long memberId = TokenUtil.getUserId(token);
            List<MemberGame> memberGames = memberGameService.listByMemberId(memberId);
            List<Long> gameIdList = memberGames.stream()
                    .map(MemberGame::getGameId)
                    .distinct()
                    .collect(Collectors.toList());
            game.setMemberValid(gameIdList.contains(id));

            List<GameTypeMap> gameTypeMaps = gameTypeMapService.listByGameId(id);
            List<Long> typeIdList = gameTypeMaps.stream()
                    .map(GameTypeMap::getTypeId)
                    .distinct()
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(typeIdList)) {
                Long typeId = typeIdList.get(0);
                GameType gameType = gameTypeService.getById(typeId);
                if (Objects.nonNull(gameType)) {
                    game.setGameType(gameType.getTypeName());
                }
            }
        }

        return new ResultVO().success(game);
    }

    @PostMapping("/saveOrUpdate")
    public ResultVO saveOrUpdate(@RequestBody Game game) {
        gameService.saveOrUpdate(game);
        gameTypeMapService.deleteByGameId(game.getId());
        if (CollectionUtil.isNotEmpty(game.getTypeIdList())) {
            LocalDateTime now = LocalDateTime.now();
            List<GameTypeMap> gameTypeMapList = game.getTypeIdList().stream()
                    .map(typeId -> new GameTypeMap(null, game.getId(), typeId, now))
                    .collect(Collectors.toList());
            gameTypeMapService.saveOrUpdateBatch(gameTypeMapList);
        }
        return new ResultVO().success();
    }





    @PostMapping("/uploadGameImg")
    public ResultVO uploadGameImg(MultipartFile file, Long gameId, HttpServletRequest request) throws IOException {
        log.info("开始上传游戏图片");
        String filename = file.getOriginalFilename();
        String extend = filename.substring(filename.lastIndexOf("."));

        String objName = "img/game/" + gameId + "-" + IdUtil.simpleUUID() + "-gameImgUrl" + extend;
        String url = OSSUtil.uploadFile(objName, file);
        String filePath = OSSUtil.BASE_PATH + objName;
        if (StringUtils.isNotEmpty(url)) {
            log.info("开始缩放图片");
            ImgUtil.scale(
                    FileUtil.file(filePath),
                    FileUtil.file(filePath),
                    0.5F
            );
            log.info("缩放完成");
        }
        log.info("游戏图片上传完成: url: {}", url);
        log.info("开始更新游戏数据");
        Game game = new Game();
        game.setId(gameId);
        game.setImgUrl(url);
        gameService.updateById(game);
        return new ResultVO().success();
    }


    @PostMapping("/uploadRecommendImg")
    public ResultVO uploadRecommendImg(MultipartFile file, Long gameId, HttpServletRequest request) throws IOException {
        log.info("开始上传游戏推荐图片");
        String filename = file.getOriginalFilename();
        String extend = filename.substring(filename.lastIndexOf("."));

        String objName = "img/game/" + gameId + "-" + IdUtil.simpleUUID() + "-recommendImgUrl" + extend;
        String url = OSSUtil.uploadFile(objName, file);
        String filePath = OSSUtil.BASE_PATH + objName;
//        if (StringUtils.isNotEmpty(url)) {
//            log.info("开始缩放图片");
//            ImgUtil.scale(
//                    FileUtil.file(filePath),
//                    FileUtil.file(filePath),
//                    0.5F
//            );
//            log.info("缩放完成");
//        }
        log.info("推荐图片上传完成: url: {}", url);
        log.info("开始更新游戏数据");
        Game game = new Game();
        game.setId(gameId);
        game.setRecommendImgUrl(url);
        gameService.updateById(game);
        return new ResultVO().success();
    }

    @PostMapping("/uploadGameDetailImg")
    public ResultVO uploadGameDetailImg(List<MultipartFile> fileList, Long id, HttpServletRequest request) throws IOException {
        log.info("开始上传游戏详情图片, file count: {}", fileList.size());
        Game game = gameService.getById(id);
        log.info("查到游戏: gameId: {}", game.getId());
        String url = "";
        for (int i = 0; i < fileList.size(); i++) {
            MultipartFile f = fileList.get(i);
            String filename = f.getOriginalFilename();
            String extend = filename.substring(filename.lastIndexOf("."));

            String objName = "img/game/detail/" + game.getId() + "-" + IdUtil.simpleUUID() + "-gameDetailImgUrl" + extend;
            String currUrl = OSSUtil.uploadFile(objName, f);
            String filePath = OSSUtil.BASE_PATH + objName;
            if (StringUtils.isNotEmpty(currUrl)) {
                log.info("开始缩放图片");
                ImgUtil.scale(
                        FileUtil.file(filePath),
                        FileUtil.file(filePath),
                        0.5F
                );
                log.info("缩放完成");
            }
            log.info("游戏详情图片上传完成: url: {}", currUrl);
            url += currUrl;
            if (i != fileList.size() - 1) {
                url += ",";
            }
        }
        log.info("开始更新游戏数据: url: {}", url);
        game.setDetailImg(url);
        gameService.updateById(game);
        return new ResultVO().success();
    }

    @GetMapping("/page")
    public ResultVO page(@RequestParam Long page, @RequestParam Long pageSize, @RequestParam(required = false) String gameName) {
        LambdaQueryWrapper<Game> wrapper = new QueryWrapper<Game>().lambda()
                .like(Objects.nonNull(gameName), Game::getGameName, gameName)
                .orderByAsc(Game::getGameCode)
                .orderByDesc(Game::getCreateTime);
        Page<Game> pageResult = gameService.page(Page.of(page, pageSize), wrapper);
        return new ResultVO().success(pageResult);
    }

    @GetMapping("/pageByGameTypeAndGameName")
    public ResultVO pagepageByGameTypeAndGameName(
            @RequestParam Long page,
            @RequestParam Long pageSize,
            @RequestParam(required = false) String gameName,
            @RequestParam(required = false) Long gameTypeId,
            HttpServletRequest request
    ) {
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        Long memberId = TokenUtil.getUserId(token);
        List<MemberGame> memberGames = memberGameService.listByMemberId(memberId);
        List<Long> gameIdList = memberGames.stream()
                .map(MemberGame::getGameId)
                .distinct()
                .collect(Collectors.toList());
        IPage<Game> pageResult = gameService.page(gameName, gameTypeId, page, pageSize);
        for (Game record : pageResult.getRecords()) {
            record.setMemberValid(gameIdList.contains(record.getId()));
        }
        return new ResultVO().success(pageResult);
    }

    @DeleteMapping("/deleteGame")
    public ResultVO deleteGame(@RequestParam Long gameId) {
        gameService.removeById(gameId);
        return new ResultVO().success();
    }

//    @GetMapping("scaleAllGameImg")
//    public ResultVO scaleAllGameImg() {
//        log.info("开始缩放所有游戏图片");
//        List<File> fileList = Arrays.asList(FileUtil.ls("/opt/website-resource/img/game"));
//        for (File file : fileList) {
//            String path = file.getPath();
//            ImgUtil.scale(FileUtil.file(path), FileUtil.file(path), 0.5F);
//        }
//        log.info("缩放完成");
//        return new ResultVO().success();
//    }

    @PostMapping("/richTextUpload")
    public String richTextUpload(MultipartFile file) throws IOException {
        String filename = file.getOriginalFilename();
        log.info("收到富文本上传图片: fileName: {}", filename);
        if (StringUtils.isBlank(filename)) {
            return "";
        }
        String extend = filename.substring(filename.lastIndexOf("."));
        String objName = "img/rich/" + IdUtil.simpleUUID() + extend;
        String url = OSSUtil.uploadFile(objName, file);
        JSONObject json = new JSONObject();
        json.put("errno", 0);
        JSONObject dataJson = new JSONObject();
        dataJson.put("url", url);
        json.put("data", dataJson);
        return json.toJSONString();
    }

    @GetMapping("/list")
    public ResultVO list() {
        LambdaQueryWrapper<Game> wrapper = new QueryWrapper<Game>().lambda()
                .orderByAsc(Game::getGameCode);
        List<Game> list = gameService.list(wrapper);
        return new ResultVO().success(list);
    }

}
